acpi: Disable ACPI table override if securelevel is set
authorLinn Crosetto <linn@hpe.com>
Fri, 4 Mar 2016 23:08:24 +0000 (16:08 -0700)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 4 Jan 2017 19:39:36 +0000 (19:39 +0000)
From the kernel documentation (initrd_table_override.txt):

  If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible
  to override nearly any ACPI table provided by the BIOS with an
  instrumented, modified one.

When securelevel is set, the kernel should disallow any unauthenticated
changes to kernel space. ACPI tables contain code invoked by the kernel, so
do not allow ACPI tables to be overridden if securelevel is set.

Signed-off-by: Linn Crosetto <linn@hpe.com>
[bwh: Forward-ported to 4.7: ACPI override code moved to drivers/acpi/tables.c]

Gbp-Pq: Topic features/all/securelevel
Gbp-Pq: Name acpi-disable-acpi-table-override-if-securelevel-is-s.patch

arch/x86/kernel/setup.c
drivers/acpi/tables.c

index a851532da8b906eefe222068171c34a1becf33d1..e2d0b6104de6e86d8a2f1b6b925d2f82ee8be40f 100644 (file)
@@ -1153,6 +1153,12 @@ void __init setup_arch(char **cmdline_p)
        /* Allocate bigger log buffer */
        setup_log_buf(1);
 
+#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL
+       if (boot_params.secure_boot) {
+               set_securelevel(1);
+       }
+#endif
+
        reserve_initrd();
 
        acpi_table_upgrade();
@@ -1161,12 +1167,6 @@ void __init setup_arch(char **cmdline_p)
 
        io_delay_init();
 
-#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL
-       if (boot_params.secure_boot) {
-               set_securelevel(1);
-       }
-#endif
-
        /*
         * Parse the ACPI tables for possible boot-time SMP configuration.
         */
index 9f0ad6ebb368a9245c04993ba2c088144b95df02..0969d0b7b42f61e1e3ef7abbe94bc95e035d0fd9 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/memblock.h>
 #include <linux/initrd.h>
 #include <linux/acpi.h>
+#include <linux/security.h>
 #include "internal.h"
 
 #ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -543,6 +544,12 @@ void __init acpi_table_upgrade(void)
        if (table_nr == 0)
                return;
 
+       if (get_securelevel() > 0) {
+               pr_notice(PREFIX
+                       "securelevel enabled, ignoring table override\n");
+               return;
+       }
+
        acpi_tables_addr =
                memblock_find_in_range(0, ACPI_TABLE_UPGRADE_MAX_PHYS,
                                       all_tables_size, PAGE_SIZE);